ComplexHeatmap 之 Legends
点击上方关注我们
匆匆又夏天
终于来到了给热图添加图例的环节了,继续学习吧。
介绍
热图和简单注释会 自动生成图例 ,这些图例放在热图的右侧。默认情况下,复杂注释没有图例,但可以手动构建和添加它们。所有图例均由 Legend()
构造函数内部构造。在后面的章节中,我们首先介绍了 连续图例
和 离散图例
的设置,然后我们将讨论如何配置与热图和注释关联的图例,以及如何将新图例添加到图中。
所有的图例(无论是单个图例还是一组图例)都属于 Legends 类。该类只有一个 slot grob,它是真正的 grid::grob
对象或记录如何绘制图形的 grid::gTree
对象。Legends 类的包装和为该类设计的方法使图例成为单个对象,并且可以像点一样绘制并指定视口上的位置。
热图和注释的图例可以由 Heatmap()
中的 heatmap_legend_param 参数或 HeatmapAnnotation()
中的 annotation_legend_param 参数控制。Legend()
函数中的大部分参数都可以直接设置在参数名称相同的两个参数中。设置热图图例和注释图例参数的详细信息在后面介绍。
1、连续型图例
由于大多数热图包含连续值,我们首先介绍连续图例的设置。
连续图例需要一个颜色映射函数,该函数应该由 circlize::colorRamp2()
生成。在自动生成的热图图例和注释图例中,颜色映射函数通过来自 Heatmap() 或 HeatmapAnnotation() 函数的 col
参数传递,而如果构建自定义图例,则需要提供颜色映射函数。
颜色映射函数中提供的 break (例如以下示例中的 c(0, 0.5, 1))与图例中的 break 不完全相同)。图例中显示的最终 break 值经过内部调整,使标签数量接近 5 或 6。
首先我们展示一个垂直连续图例的默认样式:
library(circlize)
col_fun = colorRamp2(c(0, 0.5, 1), c("blue", "white", "red"))
lgd = Legend(col_fun = col_fun, title = "foo")
lgd 是 Legends 类对象。图例的大小可以通过 ComplexHeatmap:::width()
和 ComplexHeatmap::height()
函数获得:
ComplexHeatmap:::width(lgd)
## [1] 9.90361111111111mm
ComplexHeatmap:::height(lgd)
## [1] 30.2744052165491mm
图例实际上是由矩形、线条和文本组成的打包图形对象。它可以通过 draw()
函数添加到绘图中。在 ComplexHeatmap pacakge 中,不需要直接在图例对象上使用 draw(),但如果在其他地方使用图例对象,它可能会很有用:
pushViewport(viewport(width = 0.9, height = 0.9))
grid.rect() # border
draw(lgd, x = unit(1, "cm"), y = unit(1, "cm"), just = c("left", "bottom"))
draw(lgd, x = unit(0.5, "npc"), y = unit(0.5, "npc"))
draw(lgd, x = unit(1, "npc"), y = unit(1, "npc"), just = c("right", "top"))
popViewport()
如果只想配置热图或注释生成的图例,则无需自行构建 Legends 对象。后面引入的参数可以通过 Heatmap() 中的 heatmap_legend_param 参数和 HeatmapAnnotation() 中的 annotation_legend_param 参数直接用于自定义图例。在以下示例中看到这些参数如何改变图例的样式仍然很好。以下是一个简单的示例,展示了如何在热图和热图注释中配置图例:
Heatmap(matrix(rnorm(100), 10),
heatmap_legend_param = list(
title = "rnorm", at = c(-2, 0, 2),
labels = c("neg_two", "zero", "pos_two")
),
top_annotation = HeatmapAnnotation(
foo = 1:10,
annotation_legend_param = list(foo = list(title = "foo_top_anno"))
))
在下面的例子中,我们只展示了如何构造图例对象,而不展示绘制图例的代码。你可以在 Legends 对象上使用 draw()
函数在图上绘制单个图例。
对于连续图例,您可以通过设置 at
手动调整图例中的 break。注意高度是自动调整的:
lgd = Legend(col_fun = col_fun, title = "foo", at = c(0, 0.25, 0.5, 0.75, 1))
对应的标签由 labels 设置:
lgd = Legend(col_fun = col_fun, title = "foo", at = c(0, 0.5, 1),
labels = c("low", "median", "high"))
垂直连续图例的高度由 legend_height
设置。Legend_height 只能为垂直 连续图例设置,值为图例主体的高度(不包括图例标题):
lgd = Legend(col_fun = col_fun, title = "foo", legend_height = unit(6, "cm"))
如果是垂直图例, grid_width
控制图例主体的宽度。grid_width 最初是为 离散图例 设计的,其中图例中的每个级别都是一个网格,但这里我们对控制图例宽度的参数使用相同的名称:
lgd = Legend(col_fun = col_fun, title = "foo", grid_width = unit(1, "cm"))
标签的图形参数由 labels_gp
控制:
lgd = Legend(col_fun = col_fun, title = "foo", labels_gp = gpar(col = "red", font = 3))
图例的边框以及中断值的刻度由边框控制。border
的值可以是逻辑值或颜色字符串:
lgd = Legend(col_fun = col_fun, title = "foo", border = "red")
title_position
控制标题的位置。对于垂直图例,该值应为 topleft
、topcenter
、lefttop-rot
和 leftcenter-rot
之一。以下两个图显示了 lefttop-rot 标题和 leftcenter-rot 标题的效果:
lgd = Legend(col_fun = col_fun, title = "foooooooo", title_position = "lefttop-rot",
legend_height = unit(4, "cm"))
lgd = Legend(col_fun = col_fun, title = "foooooooo", title_position = "leftcenter-rot",
legend_height = unit(4, "cm"))
图例标题和标签可以设置为数学公式:
lgd = Legend(col_fun = col_fun, title = expression(hat(beta) == (X^t * X)^{-1} * X^t * y),
at = c(0, 0.25, 0.5, 0.75, 1), labels = expression(alpha, beta, gamma, delta, epsilon))
以使用 gridtext
包添加更复杂的文本:
lgd = Legend(col_fun = col_fun,
title = gt_render("<span style='color:orange'>**Legend title**</span>"),
title_gp = gpar(box_fill = "grey"),
at = c(-3, 0, 3),
labels = gt_render(c("<span style='color:blue'>*negative*</span> three", "zero",
"<span style='color:red'>*positive*</span> three"))
)
水平连续图例的设置与垂直图例几乎相同,只是现在 legend_width
控制图例的宽度,标题位置只能是 topcenter
、topleft
、lefttop
和 leftcenter
之一。
水平图例的默认样式:
lgd = Legend(col_fun = col_fun, title = "foo", direction = "horizontal")
手动设置 at :
lgd = Legend(col_fun = col_fun, title = "foo", at = c(0, 0.25, 0.5, 0.75, 1),
direction = "horizontal")
手动设置标签:
lgd = Legend(col_fun = col_fun, title = "foo", at = c(0, 0.5, 1),
labels = c("low", "median", "high"), direction = "horizontal")
设置图例宽度:
lgd = Legend(col_fun = col_fun, title = "foo", legend_width = unit(6, "cm"),
direction = "horizontal")
设置标签的图形参数:
lgd = Legend(col_fun = col_fun, title = "foo", labels_gp = gpar(col = "red", font = 3),
direction = "horizontal")
设置标签的旋转:
lgd = Legend(col_fun = col_fun, title = "foo", labels_rot = 45,
direction = "horizontal")
标题可以设置为 topleft
、topcenter
或 lefttop
和 leftcenter
:
lgd = Legend(col_fun = col_fun, title = "foooooooo", direction = "horizontal",
title_position = "lefttop")
在我们上面展示的例子中,每两个中断值之间的间隔是相等的。实际上 at 也可以设置为间隔不等的中断值。在这种情况下,图例上的刻度仍然在原始位置,而相应的文本被移动以消除重叠。然后,有连接刻度线和标签的线
:
lgd = Legend(col_fun = col_fun, title = "foo", at = c(0, 0.1, 0.15, 0.5, 0.9, 0.95, 1))
如果标签不需要调整,它们仍然在原来的地方:
lgd = Legend(col_fun = col_fun, title = "foo", at = c(0, 0.3, 1),
legend_height = unit(4, "cm"))
水平图例类似:
lgd = Legend(col_fun = col_fun, title = "foo", at = c(0, 0.1, 0.15, 0.5, 0.9, 0.95, 1),
direction = "horizontal")
将标签的旋转设置为 90 度:
lgd = Legend(col_fun = col_fun, title = "foo", at = c(0, 0.1, 0.15, 0.5, 0.9, 0.95, 1),
direction = "horizontal", title_position = "lefttop", labels_rot = 90)
当 title
的位置设置为 lefttop 时,在计算 label 的调整位置时也会考虑title 下方的区域
:
lgd = Legend(col_fun = col_fun, title = "foo", at = c(0, 0.1, 0.5, 0.75, 1),
labels = c("mininal", "q10", "median", "q75", "maximal"),
direction = "horizontal", title_position = "lefttop")
如果 at 以 降序 设置,则图例反转
,即最小值位于图例的顶部:
lgd = Legend(col_fun = col_fun, title = "foo", at = c(1, 0.8, 0.6, 0.4, 0.2, 0))
大多数连续的图例都有等距的中断,例如 第一个和第二个中断之间的距离与第二个和第三个中断之间的距离相同。但是,仍然存在一些特殊情况,用户希望设置 不等距的图例中断
。
在以下示例中,颜色映射函数 col_fun_prop
将在 c(0, 0.05, 0.1, 0.5, 1) 中具有中断的比例值可视化。距离不等的图例中断可能反映了 c(0, 1) 中值的不同重要性。例如,也许我们想在区间 c(0, 0.1) 中看到更多细节。
以下是图例的默认样式,其中从 0 到 1 以相等的距离选择中断:
col_fun_prop = colorRamp2(c(0, 0.05, 0.1, 0.5, 1),
c("green", "white", "red", "black", "blue"))
lgd = Legend(col_fun = col_fun_prop, title = "Prop")
如果我们手动选择中断值,颜色条保持不变。标签被移动,线将它们连接到原始位置。在这种情况下,颜色条中的距离仍然与中断值的实际差异成正比,即 0.5 和 1 之间的距离比 0 和 0.1 长五倍:
col_fun_prop = colorRamp2(c(0, 0.05, 0.1, 0.5, 1),
c("green", "white", "red", "black", "blue"))
lgd = Legend(col_fun = col_fun_prop, title = "Prop",
at = c(0, 0.05, 0.1, 0.5, 1))
从版本 2.7.1 开始,Legend()
函数有一个新参数 break_dist
,用于控制图例中两个相邻中断值之间的距离。可能会令人困惑,但从这里开始,当我提到“中断距离”时,它总是指图例中的视觉距离。
break_dist 的值的长度应为 1,这意味着所有中断值在图例中具有相等的距离,或 length(at) - 1:
lgd = Legend(col_fun = col_fun_prop, title = "Prop", break_dist = 1)
在下面的示例中,顶部的两个中断间隔比底部的两个间隔长三倍:
lgd = Legend(col_fun = col_fun_prop, title = "Prop", break_dist = c(1, 1, 3, 3))
如果我们通过 legend_height
参数增加图例高度,标签将有足够的空间,它们的位置不再调整:
lgd = Legend(col_fun = col_fun_prop, title = "Prop", break_dist = c(1, 1, 3, 3),
legend_height = unit(4, "cm"))
想象以下案例,我们想对 c(0, 0.1) 中的值使用一种颜色方案,对 c(0.1, 1) 中的值使用第二种颜色方案,可能是因为我们想强调这两个区间 非常不同
。颜色映射可以定义为:
col_fun2 = colorRamp2(c(0, 0.1, 0.1+1e-6, 1), c("white", "red", "yellow", "blue"))
所以在这里我只是在 0.1 上添加了一个微小的偏移 (1e-6) 并将其设置为第二个配色方案的下限。传说看起来像:
lgd = Legend(col_fun = col_fun2, title = "Prop", at = c(0, 0.05, 0.1, 0.5, 1),
break_dist = c(1, 1, 3, 3), legend_height = unit(4, "cm"))
未完待续。
收官!
代码 我上传到 QQ 群 老俊俊生信交流群
文件夹里。欢迎加入。加我微信我也拉你进 微信群聊 老俊俊生信交流群
哦。
群二维码:
老俊俊微信:
知识星球:
所以今天你学习了吗?
欢迎小伙伴留言评论!
今天的分享就到这里了,敬请期待下一篇!
最后欢迎大家分享转发,您的点赞是对我的鼓励和肯定!
如果觉得对您帮助很大,赏杯快乐水喝喝吧!
往期回顾
◀ComplexHeatmap 之 Heatmap List 续(二)
◀ComplexHeatmap 之 Heatmap List 续(一)
◀ComplexHeatmap 之 Heatmap List
◀ComplexHeatmap 之 Heatmap Annotations 续(三)
◀ComplexHeatmap 之 Heatmap Annotations 续(二)
◀ComplexHeatmap 之 Heatmap Annotations 续(一)
◀ComplexHeatmap 之 Heatmap Annotations
◀ComplexHeatmap 之 A Single Heatmap 续(二)
◀ComplexHeatmap 之 A Single Heatmap 续(一)